package com.times.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.log4j.Logger;

import com.times.exception.SystemException;

/**
 * <p>反射工具类 </p>
 * @author 
 * @version 2010-12
 */
public class ReflectUtils {
    
    private static Logger logger = Logger.getLogger(ReflectUtils.class);


    /**
     * 循环向上转型, 获取对象的 DeclaredMethod
     * 
     * @param object
     * @param methodName
     * @param parameterTypes
     * @return
     */
    public static Method getDeclaredMethod(Object object, String methodName,
            Class<?>[] parameterTypes) {
        for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
                .getSuperclass()) {
            try {
                // superClass.getMethod(methodName, parameterTypes);
                return superClass.getDeclaredMethod(methodName, parameterTypes);
            } catch (NoSuchMethodException e) {
                // Method 不在当前类定义, 继续向上转型
            }
        }
        logger.warn("get object null method, the class is " + object.getClass().getName());

        return null;
    }

    /**
     * 循环向上转型, 获取对象的 DeclaredField
     * 
     * @param object
     * @param filedName
     * @return
     */
    public static Field getDeclaredField(Class<?> clazz, String filedName) {
        for (Class<?> superClass = clazz; superClass != Object.class; superClass = superClass
                .getSuperclass()) {
            try {
                return superClass.getDeclaredField(filedName);
            } catch (NoSuchFieldException e) {
                // Field 不在当前类定义, 继续向上转型
            }
        }
        logger.warn("get object null method, the class is " + clazz.getName());
        return null;
    }

    /**
     * 直接调用对象方法, 而忽略修饰符(private, protected)
     * 
     * @param object
     * @param methodName
     * @param parameterTypes
     * @param parameters
     * @return
     * @throws InvocationTargetException
     * @throws IllegalArgumentException
     */
    public static Object invokeMethod(Object object, String methodName,
            Class<?>[] parameterTypes, Object[] parameters)
            throws InvocationTargetException {
        Method method = getDeclaredMethod(object, methodName, parameterTypes);

        if (method == null) {
            throw new IllegalArgumentException("Could not find method ["
                    + methodName + "] on target [" + object + "]");
        }

        method.setAccessible(true);

        try {
            return method.invoke(object, parameters);
        } catch (IllegalAccessException e) {
            logger.error("invoke error method "+ methodName +" in " + object.getClass().getName());
            throw new SystemException(e.getMessage());
        }
    }

    /**
     * 功能:获取指定对象中指定注解的对象值.
     * @author 
     * @version 2015-01
     * @param thisObj    指定的对象
     * @param returnType 返回类型
     * @param annatation 注解类型
     * @return 若指定对象中存在多个相同指定注解，仅返回第一个找到的注解值
     */
    public static Object getFieldByAnnatation(Object thisObj, Class<? extends Annotation> annatation) {
        for (Class<?> superClass = thisObj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {//如果子类中没有该属性则向上转型
            Field[] fields = superClass.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(annatation)) {
                    try {
                        field.setAccessible(true);
                        Object value = field.get(thisObj);
                        
                        field.setAccessible(false);
                        return value;
                    } catch (Exception e) {
                        throw new SystemException(e.getMessage());
                    }
                }
            }
        }
        return null;
    }
}
